Most
of you will be familiar with the Listbox control in dialogs, however this
tutorial deals with creating a similar control, which is visually customisable
using the /draw* commands, available in mIRC.
The example I intend to use for the purpose of this tutorial is a genre
list, reading from a stored file in the mIRC directory.
In order to make a usable listing system, the following
tasks need to be undertaken.
1.
A primary buffering system.
2.
A functional scrollbar.
3.
A basic listbox GUI.
4.
A listing process.
5.
Event handling (sclick, dclick etc).
This tutorial will systematically guide you through these
tasks with worked examples.
The
object of creating a buffering system is that it allows you to manage lists
more efficiently, for example adding or deleting lines of data. It also makes the listing system relatively
error free, and quick.
Depending
on the information you wish to list, the buffering process is slightly
different. This tutorial will
demonstrate two different types. The
first is fairly straight forward, and retrieves lines of text from a saved file
in the mIRC directory. The second creates
a buffer of filenames from a directory, much in the same way as a mp3 play list
would work.
Below
is an example of buffering from a saved text file, this utilises the file
handling routines introduced into mIRC 6.1x
alias load.buffer {
;check to ensure that the file reference isn’t already open…
if
(!$fopen(buffer)) {
;open the genre text file, to the file reference “buffer”…
.fopen
buffer $+(",$scriptdir,genre.txt,")
}
;create an @window list (-h = hidden window, -l = listbox window)…
window -hl
@buffer -1 -1 400 300
;clear buffer window to prevent appending text to the end of the
listbox…
clear
@buffer
;declare variables needed for loop…
var %x,%i =
0
;initiate
the while loop – (!$feof) causes the loop to continue until the end of the text
file is reached…
while
(!$feof) {
inc %i
;$fread(buffer) returns the next line of the text file…
%x =
$fread(buffer)
;if the next line in the text file exists, write it to the buffer
window…
if (%x)
iline @buffer %i %x
}
;all files
must be closed, after use in order to allow them to be used externally of mIRC.
.fclose
buffer
}
This should create a buffer window, with a list of music
genre types, as shown below: -
This window can now be used to
write text to a picture window.
An important identifier to consider is
$line(<window>,N), using this identifier, the text can be retrieved from
the Nth line of the buffer window.
Try this, type //echo -s $line(@buffer,35) in the active
“status window”.
The word “Acid” should echo in the “status window”.
It is also possible to determine the number of lines of
text in the buffer window using the same identifier, this will be important
when creating a scrollbar.
Try this, type //echo -s $line(@buffer,0) in the active
“status window”.
The number “126” should echo in
the “status window”.
The second buffering example is one where filenames from a
certain directory are listed, this is done using the following buffer alias.
alias dbuffer {
;create an @window list (-h = hidden window, -l = listbox window)…
window -hl
@buffer -1 -1 400 300
;clear buffer window to prevent appending text to the end of the
listbox…
clear
@buffer
;locate *.mp3 files in your selected directory, and write to the
@buffer window…
var %n =
$findfile($sdir(C:\,Select mp3 Directory),*.mp3,@buffer)
}
You can use the $findfile identifier, to write the file paths to a temporary file (@temp), and then /filter from that to the @buffer window. However, for the sake of simplicity, this step was omitted.
The result of the above alias should be similar to that of
the first example.
Before continuing to the next stage of this tutorial,
ensure that you understand the importance of this buffering stage, and are
competent at creating a listing buffer.
This is probably the most challenging aspect of creating a
picture window listbox. It does require
a fair amount of arithmetic, but is fairly straightforward. The advantage of the identifier below is
that it can be manipulated to work on any picture window, with no restrictions
on the number of scrollbars you can have on the window in question.
;$scrollbar(<@win>,<x>,<y>,<w>,<h>,<bg>,<fg>,<fg
hilite>,<fg shadow>,<buffer @win>,<MAX lines in list>)
The identifier requires 11 parameters, which MUST be
assigned.
$1 = Name of Picture Window (Syntax = @name).
$2 = x co-ordinate.
$3 = y co-ordinate.
$4 = w co-ordinate (width).
$5 = h co-ordinate (height).
$6 = Background Colour.
$7 = Foreground Colour.
$8 = Foreground Highlight.
$9 = Foreground Shadow.
$10 = Name of Buffer Window, Linked With Listbox.
$11 = Max Lines To Display In Listbox.
;descriptive breakdown of
$scrollbar(…) identifier, and relevant commands.
alias scrollbar {
;if alias is not called as an identifier return…
if (!$isid)
{ return }
;else continue to process…
else {
;declare variable for while loop…
var %i =
1
;draw a rectangle according to co-ordinates and colour data
provided in identifier, to act as background…
drawrect
-rnf $1 $6 1 $2 $3 $4 $5
;initiate while loop, check if hashed data exists for %i…
while
($hget(scrollbar. $+ $1,%i)) inc %i
;if hash data for %i does not exist, add it…
hadd -m
scrollbar. $+ $1 %i $+($2,/,$3,/,$4,/,$5,/,$6,/,$7,/,$8,/,$9,/,$10,/,$11)
}
}
;Scrollbar Mouse Events
;window name is not specified, * acts as a wildcard window name…
menu * {
mouse: {
;ensure that mouse event is only triggered when the left mouse button is
clicked…
if
($mouse.key & 1) {
;declare variable for loop…
var %r
= 1
;while loop is set to search through saved hash data for active window…
while
($hget(scrollbar. $+ $active,%r)) {
;tokenize assigns each saved parameter, to an $N identifier, for example
$1,$2,$3…
tokenize 47 $ifmatch
;check if the mouse cursor is over the saved co-ordinates for scrollbar,
if it is, make it scroll…
if
($inrect($mouse.x,$mouse.y,$1,$2,$3,$4)) { scroll.update %r
$ceil($calc((($mouse.y - $2) / $4) * 100)) }
inc
%r
}
}
}
;similar process to above, however this is for the on sclick event…
sclick: {
var %r =
1
while
($hget(scrollbar. $+ $active,%r)) {
tokenize 47 $ifmatch
if ($inrect($mouse.x,$mouse.y,$1,$2,$3,$4))
{ scroll.update %r $ceil($calc((($mouse.y - $2) / $4) * 100)) }
inc %r
}
}
}
This alias assigns your commands for the scrollbar.
alias scroll.update {
;if the active window is “name of your picture window” continue…
if ($active
== @test) {
;if scrollbar id is “id of scrollbar” draw the scroll thumb and run
command…
if ($1 ==
1) { draw.scroll @test $1 $2 | echo 8 Scroll One: $2 }
if ($1 ==
2) { draw.scroll @test $1 $2 | echo 4 Scroll Two: $2 }
}
if ($active
== @test1) {
if ($1 ==
1) { draw.scroll @test1 $1 $2 | draw.buffer }
}
}
The alias below, is very important. It calculates and draws the position of the scrollbar thumb, according to the data saved in hash for the specific scrollbar.
alias draw.scroll {
;declare variables of scrollbar data
var %win =
$1,%name = $2,%pos = $3
;tokenize specific hash data for scrollbar and assign parameters to $N
identifiers…
tokenize 47
$hget(scrollbar. $+ %win,%name)
;calculate size of scrollbar thumb, according to amount of data
to be listed, ensure there is a minimum thumb size…
var %sep =
$calc($iif($line($9,0) <= $10 ,1,$iif($calc($10 / $line($9,0)) <
0.05,0.05,$calc($10/ $line($9,0)))))
;declare variable for thumb shadow colour…
var %sh =
$calc($8 + $rgb(20,20,20))
;declare variables for thumb co-ordinates…
var %x $1,
%y $calc(((%pos / 100 * $4) * $calc(1 - %sep)) + $2), %w $3, %h $ceil($calc($4
* %sep))
;draw a rectangle over background, so thumb position can be refreshed…
drawrect
-rnf %win $5 1 $1 $2 $3 $4
;draw rectangle to represent thumb on scrollbar…
drawrect
-rnf %win $6 1 %x %y %w %h
;add 3d detail onto scrollbar thumb…
drawrect
-rn %win $8 1 %x %y %w %h
drawline
-rnf %win $7 1 $calc(%x + 1) $calc((%y + %h) - 2) $calc(%x + 1) $calc(%y + 1)
$calc((%x + %w) - 1) $calc(%y + 1)
drawline -rnf
%win %sh 1 $calc(%x + 1) $calc((%y + %h) - 2) $calc((%x + %w) - 2) $calc((%y +
%h) - 2) $calc((%x + %w) - 2) $calc(%y + 1)
;drawdot command refreshes the scrollbar as –n flags are used in draw
commands…
drawdot
$active
}
Below is just a sample alias of how the scrollbar
identifier is used…
alias test {
;free all hash data for active window…
hfree -w
*@test
;if picture window is open refresh it…
if
($window(@test)) { close -@ @test | window -ak0hdBpfo +d @test -1 -1 65 160 }
;if not open it…
else {
window -ak0hdBpfo +d @test -1 -1 65 160 }
;clear the picture window…
clear @test
;draw a rectangle for the window background…
drawrect
-rf @test $rgb(face) 1 0 0 65 160
;draw two scrollbars with the custom identifier…
$scrollbar(@test,10,10,15,140,$rgb(243,240,234),$rgb(233,230,224),$rgb(255,255,255),$rgb(200,200,200),@buffer,5)
$scrollbar(@test,40,10,15,140,$rgb(243,240,234),$rgb(233,230,224),$rgb(255,255,255),$rgb(200,200,200),@buffer,15)
}
The result of the above command is shown below…
The scrollbars should be fully
functional, i.e. mouse events should work.
As you scroll on them, they should echo the command that
has been assigned to them, in the status window.
The thumbs sizes are different because of the Parameter
<Max lines to be listed> in the $scrollbar identifier, see above, those
values have been highlighted.
That completes the section on the scrollbar. At this stage you should understand and be able to use the $scrollbar(…) identifier. Please bare in mind that this identifier is rather basic, and does not include scroll up/down buttons. Those should be a fairly easy addition if you are competent at using picture windows. The point of the tutorial was to demonstrate the use of a scrollbar in a picture window list box, and this certainly achieves that goal.
Feel free to use this identifier for other purposes as it
does not necessarily have to be used for list boxes.
The design of the listbox is something that you can decide for yourself, however the one below should suffice for this tutorial. Please remember that the main advantage of using picture windows over dialog controls is that, the design is completely customisable that includes colours/fonts/shapes etc
So be adventurous, I’ve tried to keep this simple for the
purpose of this tutorial.
The following alias, will create a window called @test1,
onto which a listbox will be drawn…
alias test1 {
;delete any relevant hash tables for new window…
hfree -w
*@test1
;if the window is open, refresh it…
if
($window(@test1)) { close -@ @test1 | window -ak0hdBCpfo +d @test1 -1 -1 180
174 }
;else open it…
else {
window -ak0ChdBpfo +d @test1 -1 -1 180 174 }
;clear the picture window…
clear @test1
;draw rectangle for window background...
drawrect
-rf @test1 $rgb(face) 1 0 0 180 174
;draw the 3d effect of window background…
drawrect
-rn @test1 $rgb(180,180,180) 1 0 0 180 174
drawline
-rn @test1 $rgb(255,255,255) 1 1 172 1 1 178 1
drawline
-rn @test1 $rgb(210,210,210) 1 1 172 178 172 178 1
;draw rectangle for listbox background...
drawrect
-nrf @test1 $rgb(243,240,234) 1 10 10 160 152
;draw 3d sunk in effect for listbox background…
drawline
-rn @test1 $rgb(200,200,200) 1 10 163 10 10 169 10
drawline
-rn @test1 $rgb(255,255,255) 1 10 163 169 163 169 11
;draw rectangle for listbox header...
drawrect
-rnf @test1 $rgb(233,230,224) 1 12 12 156 15
;draw the 3d effect for listbox header…
drawrect
-rn @test1 $rgb(200,200,200) 1 12 12 156 15
drawline
-rn @test1 $rgb(220,220,220) 1 13 25 166 25 166 13
drawline
-rn @test1 $rgb(255,255,255) 1 13 24 13 13 167 13
;draw the header title text, drawing twice with a lighter colour
behind gives the text an engraved effect…
;the light text has to be offset by 1px on both the x and y
co-ordinates…
drawtext
-rn @test1 $rgb(255,255,255) tahoma -7 21 15 Genre List
drawtext
-rn @test1 $rgb(160,160,160) tahoma -7 20 14 Genre List
;add a scrollbar for the listbox using the $scrollbar
identifier....
$scrollbar(@test1,156,28,12,134,$rgb(233,230,224),$rgb(233,230,224),$rgb(255,255,255),$rgb(200,200,200),@buffer,15)
drawdot
@test1
}
The alias above produces a window, which looks like the one
below:-
This is just the bare skeleton of
the listbox, as yet it doesn’t list data and it doesn’t allow for mouse events.
That’s all coming up…
At this stage you should have a listbox with a working
scrollbar.
Remember that all colours and sizes are customisable. You should just use the above alias as an
example and play around with it, make bigger/smaller listbox’s. It would be easier to make an identifier to
draw the listbox skeleton, in which you can vary sizes by assigning x,y,w,h
parameters and vary colours by assigning $rgb(…) values. In a similar way to the $scrollbar(…)
identifier. However you would not need
any window events for it, as each window requires its own unique coding.
This concludes this section of the tutorial, before moving
on, you should ensure that you have created a listbox GUI that looks appealing
to you, and that the scrollbar works as it should. If it doesn’t go back and check the $scrollbar(…) identifier and
ensure you have assigned all 11 parameters.
This process involves the retrieving of data from the
buffer window and displaying it onto the picture window. As described earlier in the tutorial, the
identifier that is most useful in retrieving data is $line(@window,N). It allows you to retrieve text from a
specific line of a buffer window.
The listing process involves a limited while loop, the
limit would be the number of lines you wish to display at any given time, i.e.
the MAX numbers of lines in the listbox.
The draw.buffer alias below, is an example of this limited
while loop, the text drawn on the picture window has to be relevant to the
position of the scrollbar thumb. For
this reason the position of the thumb has to be predetermined mathematically
from the hash data of the scrollbar, in question.
It is necessary to have an alias like this for each picture
window listbox you create, the downsides of this is are that it can be fairly
time consuming and it does take up a fair amount of space. This alias can be expanded upon, if for
example you wish to create a listbox with multiple columns, you only need to
add the data for the other columns into the same buffer window and add separate
/drawtext commands into the same loop.
;descriptive breakdown of the listing
process…
alias draw.buffer {
;declare variable %t, this allows you to set the starting point for the
listing… e.g. draw.buffer 50, will list from line 50 onwards…
var %t = $1
;retrieve hash data for the scrollbar, you know that there is only one
scrollbar on the window, so there is no need to use a while loop…
if
($hget(scrollbar. $+ @test1,1)) {
tokenize 47 $ifmatch }
;if number of lines in buffer is less than MAX lines in list, and set
variable to starting point…
if
($line(@buffer,0) <= 10) set %genre.y $round($calc(($mouse.y - $2) / $4 *
$line(@buffer,0)),0)
;if number of lines in buffer is more than MAX lines in list, do as above, however you have to subtract $calc(MAX lines – 1) from the number of lines in the buffer, in this case you subtract 9, highlighted below…
elseif
($line(@buffer,0) > 10) { set %genre.y $ceil($calc(($mouse.y - $2) / $4 *
$calc($line(@buffer,0) - 9)))) }
;if the starting point is 0, set it to 1 as there is no line 0 of text
in the buffer window…
if
(%genre.y == 0) { set %genre.y 1 }
;if %t has been declared set the starting point to %t…
if (%t) {
set %genre.y $ifmatch }
;draw a rectangle of the same colour to the listbox background, so
listbox text can be refreshed when scrolling…
drawrect
-rfn @test1 $rgb(243,240,234) 1 12 28 144 134
;if picture window is open, continue…
if
($window(@test1)) {
;declare loop variables…
var %x2 =
%genre.y
var %x =
1
;set up a LIMITING loop, here the limit is 10, i.e. this will list 10
lines in the picture window…
while (%x
<= 10) {
;check to ensure, that the buffer contains relevant text…
if
($line(@buffer,%x2)) {
;draw text in a lighter colour, with a 1px offset, to create the
engraved text effect…
drawtext -rnc @test1 $rgb(255,255,255) "verdana" -7 18 $calc((13 * %x) + 18) 140 14 $line(@buffer,%x2)
;draw text by
increasing the Y co-ordinate, this is done by using a multiplier, in this case
it is 13. Increasing this number would
create a bigger space between lines of text, decreasing it would reduce the
space…
;The text is
retrieved using $line(@buffer,%x2), %x2 returns the line number…
drawtext -rnc @test1 $rgb(140,140,140) "verdana" -7 17 $calc((13 * %x) + 17) 140 14 $line(@buffer,%x2)
}
inc %x
inc %x2
}
;drawdot refreshes the window, as –n flags are used in the /draw
commands…
drawdot
@test1
}
}
The listing process should be fairly straightforward, the
biggest problem, is likely to be understanding how to calculate the Y
co-ordinate of the text. To calculate
this, you need to use a multiplier value, so that the text is spaced evenly
each time a line is added to the listbox.
In the above example the value 13 was used. A constant value is also added, this is to determine the Y
position in accordance to the listbox position and the header, in the above
alias a value of 17 is added.
Let calculate the Y- position of the first line of text…
Y co-ordinate = $calc((13 * %x) + 17)
Y co-ordinate = $calc((13 * 1) + 17) … %x represents line
number
Y co-ordinate = $calc(13 + 17)
Therefore Y co-ordinate for Line 1 of listbox text = 30
This process is carried out for each of the ten lines
listed.
The result of the listing process is shown below:
On the /test1 alias which opens the
listbox window, append the following two lines of text to the end of the alias,
before the /drawdot command. It
displays the text and draws the scrollbar thumb in the correct position…
draw.buffer 1
draw.scroll @test1 1 $calc((%genre.y / $line(@buffer,0)) * 100)
%genre.y is the starting line (N) of text on the
picture window.
This concludes the section of this tutorial on listing data
from a buffer window to a picture window.
Before continuing, ensure that you are competent at creating listbox
buffers and are able to retrieve data and draw onto a picture window. Experiment, by increasing/decreasing Y
co-ordinate multiplier values, and change the font to what ever you suits your
needs, it can be changed by editing the “verdana” parameter in the /drawtext command. The “………” are used so fonts
which have spaces in the name can be used.
The font size is the –7, this can also be edit to suit your needs.
This is one of the more challenging tasks to complete as it
can cause a lot of confusion, and does take a while to understand fully.
The object of the task is so that the listbox can have some
actual function rather than, just be a utility to display data, mIRC has built
in routines for mouse events, which can be used, however you may choose to use
a dll, like band.dll by xhaker, to achieve the same thing.
The task involves, clicking on the text listed in the
listbox and somehow highlighting it and also returning the text, i.e. in the
form of an echo. This is made difficult
by the fact that the text co-ordinates are not stored values, i.e. they are
unknown, so they must be calculated.
The example below does this, very accurately.
;descriptive breakdown of the mouse
event handling…
menu @test1 {
sclick: {
;check and ensure that the mouse event occurs within the
listbox ONLY, and NOT over the header/scrollbar…
if
($inrect($mouse.x,$mouse.y,12,28,144,132)) {
;as you need to calculate text position, you need to know the height of the text. The letter T is used as it is only of the tallest letters in the alphabet, and as yet you can’t retrieve the actual text in the listbox…
var %h
= $calc($height(T,verdana,-7) + 1)
;the %p
variable returns the line number of the @buffer window, on which the relevant
text is…
;calculating
%p is difficult to understand, however it involves determining the Y
co-ordinate. In the example below the
value of 30 that is subtracted from $mouse.y is the same value we calculated
for the Y co-ordinate of the first line of text, in the previous section of
this tutorial…
;the value
obtained is then divided by the height of the text, and returned as an integer
value…
;clicking on
the listbox should now return values of 1-10 depending on what line you click…
;the
%genre.y is added so that the line values greater than 10 can be determined.
(%genre.y is the starting line number of the list)…
;you can now return the text of lines by clicking on them, in the picture window listbox… /echo –s $line(@buffer,%p)
var %p
= $calc($int($calc(($mouse.y - 30) / %h)) + %genre.y)
;the %z variable is the same as %p, with one difference, it does not consider the %genre.y variable, so it therefore only returns numbers 1-10, this is important for highlighting purposes…
var %z
= $int($calc(($mouse.y - 30) / %h))
;now clicking on the lines in the picture window listbox will cause an
echo of the line in the status window…
echo -s
sclick: $line(@buffer,%p)
;if %select variable is defined, continue…
if
(%select) {
;draw over previously selected line, with listbox background colours…
drawreplace -nr @test1 $rgb(219,225,232) $rgb(243,240,234)14 %select 139
13
drawrect -rn @test1 $rgb(243,240,234) 1 14 %select 139 13
}
;this is where the calculations are made to highlight a certain row of
the listbox…
;the %z value calculated above is multiplied by the SAME multiplier used
in the listing process…
;then the Y co-ordinate for the first line of text in the listbox is
added…
set
%select $calc((%z * 13) + 30)
;a coloured rectangle is drawn over the selected text…
drawreplace -nr @test1 $rgb(243,240,234) $rgb(219,225,232) 14 $calc((%z
* 13) + 30) 139 13
drawrect -nr @test1 $rgb(157,167,177) 1 14 $calc((%z * 13) + 30) 139 13
drawdot
@test1
}
}
}
The above is just an example of an sclick event. The same can be done for Dclick/Uclick/Rclick/Drop events, depending on what you want to use the list box for.
The result of the adding in mouse events for the listbox is
shown below…
This is the final product, a fully
functional listbox, which can be customised however you want.
Each time you create a new listbox, don’t forget to update
the /scroll.update alias, other wise the scrollbar won’t work…
To run the example copy all of the example code above into
your mIRC remote, copy the genre.txt file from the tutorial folder into the
script directory, type /load.buffer in the active window editbox to create the
buffer file. Then add the two remaining
lines of code as indicated in section 4, (by the GUI picture). Following this, type /test1, in the active
window editbox. The above list should
open up…
I hope this tutorial has been useful, in providing you with
a better understand of how to create a listbox in a picture window, if you need
any further assistance, or wish to report a code bug, or suggested
improvements/additions please contact me using the information below.